# 数据库模型类

import datetime
from werkzeug.security import generate_password_hash, check_password_hash

from log_analysis import db


class User(db.Model):
    """用户"""
    __tablename__ = "tb_user"

    user_id = db.Column(db.Integer, primary_key=True)  # 用户ID
    user_name = db.Column(db.String(32), unique=True, nullable=False)  # 用户名称
    nick_name = db.Column(db.String(32), nullable=True, default="")  # 用户昵称
    password_hash = db.Column(db.String(128), nullable=False)  # 加密密码
    is_admin = db.Column(db.Boolean, default=False)  # 是否管理
    phone = db.Column(db.String(32), nullable=True, default="")  # 手机号码
    email = db.Column(db.String(32), nullable=True, default="")  # 邮箱地址
    last_login = db.Column(db.DateTime, default=datetime.datetime.now)  # 最后一次登录时间

    @property
    def password(self):
        raise AttributeError("当前属性不可读")

    @password.setter
    def password(self, value):
        self.password_hash = generate_password_hash(value)

    def check_passowrd(self, password):
        return check_password_hash(self.password_hash, password)

    def to_dict(self):
        resp_dict = {
            "user_id": self.user_id,
            "user_name": self.user_name,
            "nick_name": self.nick_name,
            "is_admin": self.is_admin,
            "phone": self.phone,
            "email": self.email,
            "last_login": self.last_login.strftime("%Y-%m-%d %H:%M:%S"),
        }
        return resp_dict


class Site(db.Model):
    """站点"""
    __tablename__ = "tb_site"

    site_id = db.Column(db.Integer, primary_key=True)  # 站点ID
    site_name = db.Column(db.String(32), unique=True, nullable=False)  # 站点名称
    host = db.Column(db.String(32), nullable=False, index=True)  # 站点域名
    access_log = db.Column(db.String(32), nullable=True, default="")  # 访问日志
    error_log = db.Column(db.String(32), nullable=True, default="")  # 错误日志
    link = db.Column(db.String(3000), nullable=True, default="")  # 链接网址

    def to_dict(self):
        resp_dict = {
            "site_id": self.site_id,
            "site_name": self.site_name,
            "host": self.host,
            "access_log": self.access_log,
            "error_log": self.error_log,
            "link": self.link,
        }
        return resp_dict


class AccessLog(db.Model):
    """访问日志"""
    __tablename__ = "tb_access_log"

    log_id = db.Column(db.Integer, primary_key=True)  # 日志ID
    ip = db.Column(db.String(32), nullable=False, index=True)  # IP地址
    date_time = db.Column(db.DateTime, nullable=False, index=True)  # 请求时间
    method = db.Column(db.String(32), nullable=False)  # 请求方法
    url = db.Column(db.String(3000), nullable=False)  # 请求接口
    protocol = db.Column(db.String(32), nullable=False)  # 请求协议
    status = db.Column(db.Integer, nullable=False)  # 状态码
    size = db.Column(db.Float, nullable=True)  # 流量
    referrer = db.Column(db.String(3000), nullable=True)  # 来源页面
    useragent = db.Column(db.String(3000), nullable=True)  # 设备信息

    tb_site = db.relationship("Site", backref='tb_access_log')  # 关联 tb_site 表
    site_id = db.Column(db.Integer, db.ForeignKey("tb_site.site_id"))  # 日志所属站点ID

    def to_dict(self):
        resp_dict = {
            "log_id": self.log_id,
            "ip": self.ip,
            "date_time": self.date_time.strftime("%Y-%m-%d %H:%M:%S"),
            "method": self.method,
            "url": self.url,
            "protocol": self.protocol,
            "status": self.status,
            "size": self.size,
            "referrer": self.referrer,
            "useragent": self.useragent,
            "site_id": self.site_id,
        }
        return resp_dict


class ErrorLog(db.Model):
    """错误日志"""
    __tablename__ = "tb_error_log"

    log_id = db.Column(db.Integer, primary_key=True)  # 日志ID
    date_time = db.Column(db.DateTime, nullable=False, index=True)  # 错误时间
    level = db.Column(db.String(32), nullable=False)  # 错误级别
    message = db.Column(db.String(3000), nullable=True)  # 错误信息
    ip = db.Column(db.String(32), nullable=False, index=True)  # IP地址
    host = db.Column(db.String(32), nullable=False)  # 请求域名
    method = db.Column(db.String(32), nullable=False)  # 请求方法
    url = db.Column(db.String(3000), nullable=False)  # 请求接口
    protocol = db.Column(db.String(32), nullable=False)  # 请求协议
    referrer = db.Column(db.String(3000), nullable=True)  # 来源页面

    tb_site = db.relationship("Site", backref='tb_error_log')  # 关联 tb_site 表
    site_id = db.Column(db.Integer, db.ForeignKey("tb_site.site_id"))  # 日志所属站点ID

    def to_dict(self):
        resp_dict = {
            "log_id": self.log_id,
            "date_time": self.date_time.strftime("%Y-%m-%d %H:%M:%S"),
            "level": self.level,
            "message": self.message,
            "ip": self.ip,
            "host": self.host,
            "method": self.method,
            "url": self.url,
            "protocol": self.protocol,
            "referrer": self.referrer,
            "site_id": self.site_id,
        }
        return resp_dict


class Remind(db.Model):
    """报错提醒"""
    __tablename__ = "tb_remind"

    remind_id = db.Column(db.Integer, primary_key=True)  # 提醒ID
    site_name = db.Column(db.String(32), nullable=False)  # 报错站点
    date_time = db.Column(db.DateTime, nullable=False, index=True)  # 报错时间
    host = db.Column(db.String(32), nullable=False)  # 报错域名
    url = db.Column(db.String(3000), nullable=False)  # 报错接口
    message = db.Column(db.String(3000), nullable=False)  # 报错信息
    remind_state = db.Column(db.Boolean, nullable=True)  # 处理状态 0:待处理, 1:已处理

    def to_dict(self):
        resp_dict = {
            "remind_id": self.remind_id,
            "site_name": self.site_name,
            "date_time": self.date_time.strftime("%Y-%m-%d %H:%M:%S"),
            "host": self.host,
            "url": self.url,
            "message": self.message,
            "remind_state": self.remind_state,
        }
        return resp_dict


class Duty(db.Model):
    """值班日历"""
    __tablename__ = "tb_duty"

    duty_id = db.Column(db.Integer, primary_key=True)  # 值班ID
    duty_date = db.Column(db.String(32), nullable=False, index=True)  # 值班日期
    duty_name = db.Column(db.String(32), nullable=False)  # 值班人员
    phone = db.Column(db.String(32), nullable=False)  # 手机号码

    tb_user = db.relationship("User", backref='tb_duty')  # 关联 tb_user 表
    user_id = db.Column(db.Integer, db.ForeignKey("tb_user.user_id"))  # 值班人id

    def to_dict(self):
        resp_dict = {
            "duty_id": self.duty_id,
            "duty_date": self.duty_date,
            "duty_name": self.duty_name,
            "phone": self.phone,
            "user_id": self.user_id,
        }
        return resp_dict


class Param(db.Model):
    """参数设置"""
    __tablename__ = "tb_param"

    param_id = db.Column(db.Integer, primary_key=True)  # 参数ID
    log_name = db.Column(db.String(32), nullable=False)  # 日志名称

    error_count = db.Column(db.Integer, nullable=True)  # 报错次数阈值(单位:次数), 默认10次
    error_time = db.Column(db.Integer, nullable=True)  # 报错时间范围(单位:分钟), 默认15分钟
    remind_time = db.Column(db.Integer, nullable=True)  # 提醒时间间隔(单位:分钟), 默认30分钟

    read_time = db.Column(db.Integer, nullable=True)  # 日志读取时长(单位:分钟), 默认10分钟
    crontab_time = db.Column(db.Integer, nullable=True)  # 定时任务间隔(单位:小时), 默认1小时
    position = db.Column(db.Integer, nullable=False)  # 当前读取位置. 默认开始位置0
    site_name = db.Column(db.String(32), nullable=False)  # 日志所属站点名称

    pv_count = db.Column(db.Integer, nullable=True)  # 总页面浏览量, 日志记录条数, 可重复
    uv_count = db.Column(db.Integer, nullable=True)  # 总访客量, 一小时内相同ip算一个访客
    iv_count = db.Column(db.Integer, nullable=True)  # 总ip数, 不重复
    max_second_requests = db.Column(db.Integer, nullable=True)  # 每秒请求数量(峰值)
    peak_time = db.Column(db.DateTime, nullable=True)  # 峰值时间点
    avg_second_requests = db.Column(db.Integer, nullable=True)  # 每秒请求数量(均值)

    flag_time = db.Column(db.String(32), nullable=True)  # 日期标记
    pv_data_hour = db.Column(db.String(2048), nullable=True)  # 指定日期 访问量: 间隔一个小时
    pv_data_half = db.Column(db.String(2048), nullable=True)  # 指定日期 访问量: 间隔半个小时
    uv_data = db.Column(db.String(2048), nullable=True)  # 指定日期 访客量: 间隔一个小时

    def to_dict(self):
        resp_dict = {
            "param_id": self.param_id,
            "log_name": self.log_name,

            "error_count": self.error_count,
            "error_time": self.error_time,
            "remind_time": self.remind_time,

            "position": self.position,
            "site_name": self.site_name,
        }
        return resp_dict


class Crontab(db.Model):
    """定时任务"""
    __tablename__ = "tb_crontab"

    crontab_id = db.Column(db.Integer, primary_key=True)  # 定时任务ID
    crontab_name = db.Column(db.String(32), unique=True, nullable=False)  # 定时任务名称
    crontab_method = db.Column(db.String(32), unique=True, nullable=False)  # 定时任务方法
    crontab_state = db.Column(db.Boolean, nullable=True)  # 处理状态 0:未启动, 1:已启动

    def to_dict(self):
        resp_dict = {
            "crontab_id": self.crontab_id,
            "crontab_name": self.crontab_name,
            "crontab_method": self.crontab_method,
            "crontab_state": self.crontab_state,
        }
        return resp_dict


class UrlRecord(db.Model):
    """URL接口访问量记录"""
    __tablename__ = "tb_url_record"

    url_id = db.Column(db.Integer, primary_key=True)  # 接口ID
    url = db.Column(db.String(3000), nullable=False)  # 接口名称
    pv_count = db.Column(db.Integer, nullable=True)  # 接口访问量, 日志记录条数, 可重复
    percent = db.Column(db.String(32), nullable=False)  # 百分比
    peak_count = db.Column(db.Integer, nullable=True)  # 峰值访问量
    peak_time = db.Column(db.DateTime, nullable=True)  # 峰值时间点
    log_name = db.Column(db.String(32), nullable=False)  # 所属日志名称

    def to_dict(self):
        resp_dict = {
            "url_id": self.url_id,
            "url": self.url,
            "pv_count": self.pv_count,
            "percent": self.percent,
            "peak_count": self.peak_count,
            "peak_time": self.peak_time,
            "log_name": self.log_name,
        }
        return resp_dict


class BodyData(db.Model):
    """人体数据"""
    __tablename__ = "tb_body_data"

    id = db.Column(db.Integer, primary_key=True)  # ID

    name = db.Column(db.String(32), nullable=False)  # 姓名
    height = db.Column(db.Float, nullable=False)  # 身高
    weight = db.Column(db.Float, nullable=False)  # 体重

    neck = db.Column(db.Float, nullable=False)  # 颈围
    shoulder_width = db.Column(db.Float, nullable=False)  # 肩宽
    arm = db.Column(db.Float, nullable=False)  # 臂围
    arm_length = db.Column(db.Float, nullable=False)  # 臂长
    chest = db.Column(db.Float, nullable=False)  # 胸围
    waist = db.Column(db.Float, nullable=False)  # 腰围
    hip = db.Column(db.Float, nullable=False)  # 臀围
    thigh = db.Column(db.Float, nullable=False)  # 大腿围
    shape_type = db.Column(db.Integer, nullable=False)  # 体型分类

    def to_dict(self):
        resp_dict = {
            "id": self.id,
            "name": self.name,
            "height": self.height,
            "weight": self.weight,

            "neck": self.neck,
            "shoulder_width": self.shoulder_width,
            "arm": self.arm,
            "arm_length": self.arm_length,
            "chest": self.chest,
            "waist": self.waist,
            "hip": self.hip,
            "thigh": self.thigh,
            "shape_type": self.shape_type,

        }
        return resp_dict

